<template>
  <div class="row vb-select">
    <label v-show="labelText" :class="labelClass">
      {{labelText}}
    </label>
    <div class='vb-select-main' :class="[colCls ? ['col',colCls,inputColSize].join('-') : '']">
      <div class='vb-select-input form-control d-flex flex-row justify-content-center align-items-center' ref='selectInput'
        :class="{'vb-select-multiple': multiple && selectedItems.length > 0,'vb-select-readonly': !editable}"
         @click="onClickSelect">
        <div class='vb-select-items flex-fill'>
          <template v-if='multiple'>
            <span class="badge bg-light text-dark" v-for="(item) in selectedItems" 
              :key="item.value" :style="{height: inputHeight ? (inputHeight + 'px') : ''}">
              <span>{{item.text}}</span>
              <button type="button" class="btn-close" @click="removeItem($event,item)"></button>
            </span>
          </template>
          <span class='vb-select-items-main' :style="{width: inputWidth && multiple && selectedItems.length > 0 ? (inputWidth + 'px') : ''}">
            <input type='text' :placeholder="(multiple && selectedItems.length > 0) || !editable ? '' : placeholder" @keydown="keydown"
              @focus="onFocus" :readonly="!editable" v-model="inputValue" @input="onInput">
          </span>
        </div>
        <div class='vb-select-icon'>
          <i :class="['bi-chevron-' + (showListgroup ? 'up' : 'down')]"></i>
        </div>
        <listgroup :data="listgroupData" v-model="showListgroup" :pre-sel-index="preSelIndex" @click-item="onClickItem"/>
      </div>
    </div>
  </div>
</template>
<script lang="ts">
import { computed, defineComponent, nextTick, onMounted, ref, SetupContext, watch } from 'vue';
import { ListgroupItem } from '../listgroup/listgroup.type';
import { UPDATE_MODEL_EVENT } from '../../utils/constants';
import useMousedownOnShow from '../../utils/hooks/useMousedownOnShow';
import { DomUtil } from '../../utils';
import Listgroup from '../listgroup/listgroup.vue';
import SelectedItems from './selectedItems';
export default defineComponent({
  components: { Listgroup },
  emits: [UPDATE_MODEL_EVENT],
  name: 'VbSelect',
  props: {
    placeholder : {type : String,default : ''},
    editable : {type : Boolean,default : false},
    multiple: {type: Boolean,default: false},
    data : {type : Array,default(){return [];}},
    //栅格类前缀 col-{{colCls}}-x
    colCls : {type : String,default: ''},
    //col-xx-2
    labelColSize : {type : Number,default: 2},
    //col-xx-10
    inputColSize : {type : Number,default: 10},
    labelText : {type : String,default: ''},
    modelValue : {type : Array,default(){return [];}}
  },
  setup(props: any,ctx: SetupContext) {
    const inputValue = ref<string | number>('');
    const selectedItems = SelectedItems(ctx);
    const inputWidth = ref<number | null>();
    const inputHeight = ref<number>(0);
    const labelClass = computed(() => {
      if(props.colCls){
        return `col-form-label ${['col',props.colCls,props.labelColSize].join('-')}`;
      }else{
        return 'form-label';
      }
    });
    const selectInput = ref<HTMLDivElement>();
    const showListgroup = ref(false);
    const preSelIndex = ref(-1);
    const listgroupData = ref<ListgroupItem[]>(props.data);
    let inputFontSize = '16px';
    function setListgroupData(isAll: boolean,data?: ListgroupItem[]){
      if(isAll){
        //props中的data最全 如果数量一致 则说明数据没有变化 最全数据
        if(props.data.length === listgroupData.value.length){
          return;
        }
        data = props.data;
      }else if(!data){
        throw("need to define data");
      }
      listgroupData.value = data as ListgroupItem[];
    }
    function onClickItem(item: ListgroupItem){
      selectItem(item);
      if(props.multiple){
        //
      }else{
        showListgroup.value = false;
      }
    }
    function selectItem(item: ListgroupItem){
      if(props.multiple){
        if(selectedItems.exist(item)){
          selectedItems.remove(item);
        }else{
          selectedItems.add(item);
        }
      }else{
        if(selectedItems.exist(item)) return;
        selectedItems.clear();
        selectedItems.add(item);
        inputValue.value = item.text;
      }
    }
    function preSelect(d: number){
      let len = listgroupData.value.length;
      if(len === 0) return;
      if(d > 0 && preSelIndex.value === len - 1){
        preSelIndex.value = -1;
      }else if(d < 0 && preSelIndex.value <= 0){
        preSelIndex.value = len;
      }
      preSelIndex.value += d;
    }
    function setPreSelect(){
      if(preSelIndex.value === -1) return;
      let target = listgroupData.value[preSelIndex.value];
      if(target){
        onClickItem(target);
        preSelIndex.value = -1;
      }
    }
    onMounted(() => {
      if(props.modelValue !== ''){
        //TODO
      }
      useMousedownOnShow(showListgroup,selectInput.value);
      if(selectInput.value){
        //获取input高度 保证span高度跟input高度一致
        const inputEl = selectInput.value.querySelector("input");
        if(inputEl){
          inputHeight.value = inputEl.offsetHeight;
          inputFontSize = DomUtil.getStyle(inputEl,'fontSize');
        }
      }
    });
    watch(() => props.modelValue,(v) => {
      //TODO
    });
    function onInput(){
      if(!props.editable) return;
      const val = inputValue.value;
      if(!val){
        setListgroupData(true);
        return;
      }
      if(!showListgroup.value){
        showListgroup.value = true;
      }
      let newData = [];
      for(let i=0,len=props.data.length;i<len;i++){
        let ii = props.data[i];
        if(ii.text.indexOf(val) !== -1){
          newData.push(ii);
        }
      }
      setListgroupData(false, newData);
      preSelIndex.value = -1;
      resizeInput();
    }
    function resizeInput(){
      if(props.multiple && selectedItems.ref.value.length > 0){
        //+1是预留光标宽度
        inputWidth.value = DomUtil.getTextWidth(inputValue.value,`font-size:${inputFontSize}`) + 1;
      }
    }
    function onFocus(){
      if(props.data.length === 0 || !props.editable) return;
      showListgroup.value = true;
    }
    watch(showListgroup,(val) => {
      if(!props.editable) return;
      if(!val){
        if(props.multiple){
          inputValue.value = '';
          setListgroupData(true);
        }else{
          const items = selectedItems.ref.value;
          if(items.length > 0){
            inputValue.value = items[0].text;
            //还原全数据
            setListgroupData(true);
          }else if(items.length === 0){
            inputValue.value = '';
          }
        }
      }
    });
    function keydown(e: any){
      if(!props.editable) return;
      switch(e.code){
      case 'ArrowUp':
        preSelect(-1);
        break;
      case 'ArrowDown':
        preSelect(1);
        break;
      case 'Enter':
        setPreSelect();
        break;
      }
    }
    function removeItem(e: Event,item: ListgroupItem){
      e.stopPropagation();
      selectedItems.remove(item);
      showListgroup.value = false;
    }
    function onClickSelect(e: Event){
      const target = e.target as HTMLElement;
      const result = DomUtil.findTargetParent(target,'vb-list-group');
      if(result){
        return;
      }
      if(props.editable){
        if(selectInput.value){
          const inputEl = selectInput.value.querySelector("input");
          inputEl && inputEl.focus();
        }
      }else{
        showListgroup.value = !showListgroup.value;
      }
    }
    return {
      inputValue,
      showListgroup,
      selectInput,
      onFocus,
      keydown,
      onClickItem,
      listgroupData,
      preSelIndex,
      labelClass,
      onInput,
      selectedItems: selectedItems.ref,
      removeItem,
      onClickSelect,
      inputWidth,
      inputHeight
    };
  }
});
</script>
<style>
  .vb-select-input{
    position: relative;
    padding:0.375rem 0.75rem;
  }
  .vb-select-input input{
    border: 0;padding: 0;
  }
  .vb-select-input input:focus{
    outline: 0;
  }
  .vb-select-readonly,.vb-select-readonly input{
    background-color: #e9ecef;
    cursor: pointer;
  }
  .vb-select-multiple{
    padding:0.1875rem 0.75rem 0.1875rem 0.375rem;
  }
  .vb-select-multiple .badge{
    margin: 0.1875rem 0.375rem 0.1875rem 0;
    padding:0;padding-left: 0.35em;
    border:1px solid #ddd;
  }
  .vb-select-items{
    display: flex;flex-wrap: wrap;
    align-items: center;cursor: text;
  }
  .vb-select-items .badge button{
    width: 0.8em;height: 0.8em;
    padding:0.55em;border-radius: 0.15em;
  }
  .vb-select-items>span{
    display: flex;flex-direction: row;align-items: center;justify-content: center;
  }
  .vb-select-items-main{
    width: 100%;
  }
  .vb-select-items-main input{
    width: 100%;
  }
  .vb-select-multiple .vb-select-items-main{
    width:5px;
  }
  .vb-select-icon{
    font-size: 0;
  }
  .vb-select-icon i{font-size: 14px;}
</style>